package com.liunian.subject.domain.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.liunian.subject.common.entity.PageResult;
import com.liunian.subject.common.enums.IsDeletedFlagEnum;
import com.liunian.subject.domain.entity.SubjectInfoBO;
import com.liunian.subject.domain.entity.SubjectOptionBO;
import com.liunian.subject.domain.handler.subject.SubjectInfoTypeFactory;
import com.liunian.subject.domain.handler.subject.SubjectInfoTypeHandler;
import com.liunian.subject.domain.service.SubjectInfoDomainService;
import com.liunian.subject.infra.basic.entity.SubjectInfo;
import com.liunian.subject.infra.basic.entity.SubjectLabel;
import com.liunian.subject.infra.basic.entity.SubjectMapping;
import com.liunian.subject.infra.basic.service.SubjectInfoService;
import com.liunian.subject.infra.basic.service.SubjectLabelService;
import com.liunian.subject.infra.basic.service.SubjectMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService {

    @Resource
    private SubjectInfoService subjectInfoService;

    @Resource
    private SubjectInfoTypeFactory subjectInfoTypeFactory;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Override
    @Transactional
    public Boolean add(SubjectInfoBO subjectInfoBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectInfoDomainServiceImpl.add.bo:{}", JSON.toJSONString(subjectInfoBO));
        }
        SubjectInfo subjectInfo = subjectInfoBO.boToEntity();
        subjectInfoService.saveSubjectInfo(subjectInfo);
        SubjectInfoTypeHandler handler = subjectInfoTypeFactory.getHandler(subjectInfoBO.getSubjectType());
        subjectInfoBO.setId(subjectInfo.getId());
        handler.add(subjectInfoBO);
        List<SubjectMapping> mappingList = new ArrayList<>();
        List<Long> categoryIds = subjectInfoBO.getCategoryIds();
        if (CollectionUtil.isEmpty(categoryIds)) {
            categoryIds = Collections.singletonList(null);
        }
        List<Long> labelIds = subjectInfoBO.getLabelIds();
        if (CollectionUtil.isEmpty(labelIds)) {
            labelIds = Collections.singletonList(null);
        }
        Long subjectId = Optional.ofNullable(subjectInfo.getId()).orElseThrow(() -> new IllegalArgumentException("subjectId cannot be null"));
        List<Long> finalLabelIds = labelIds;
        categoryIds.forEach(c -> {
            finalLabelIds.forEach(l -> {
                SubjectMapping subjectMapping = new SubjectMapping();
                subjectMapping.setSubjectId(subjectId);
                subjectMapping.setCategoryId(c);
                subjectMapping.setLabelId(l);
                subjectMapping.setCreatedAt(LocalDateTime.now());
                subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
                mappingList.add(subjectMapping);
            });
        });
        return subjectMappingService.saveBatchSubjectMapping(mappingList);
    }

    @Override
    public PageResult<SubjectInfoBO> getSubjectPage(SubjectInfoBO subjectInfoBO) {
        PageResult<SubjectInfoBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectInfoBO.getPageNo());
        pageResult.setPageSize(subjectInfoBO.getPageSize());
        SubjectInfo subjectInfo = subjectInfoBO.boToEntity();
        Page<SubjectInfo> page = subjectInfo.toPage(subjectInfoBO.getPageNo(), subjectInfoBO.getPageSize());
        IPage<SubjectInfo> subjectInfoPage = subjectInfoService.queryPage(subjectInfo, page);
        List<SubjectInfo> subjectInfoList = subjectInfoPage.getRecords();
        List<SubjectInfoBO> boList = subjectInfoList.stream().map(subjectInfoBO::entityToBo).collect(Collectors.toList());
        pageResult.setRecords(boList);
        return pageResult;
    }

    @Override
    public SubjectInfoBO querySubjectInfo(SubjectInfoBO subjectInfoBO) {
        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBO.getId());
        if (subjectInfo == null) {
            return null;
        }
        SubjectInfoTypeHandler handler = subjectInfoTypeFactory.getHandler(subjectInfo.getSubjectType());
        SubjectOptionBO optionBO = handler.query(subjectInfo.getId());
        SubjectInfoBO infoBO = subjectInfoBO.entityToBo(subjectInfo);
        infoBO.setSubjectAnswer(optionBO.getSubjectAnswer());
        infoBO.setOptionList(optionBO.getOption());
        // 获取标签名列表
        List<SubjectMapping> mappingList = subjectMappingService.selectLabelIds(subjectInfoBO.getId());
        List<Long> labelIds = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
        List<SubjectLabel> labels = subjectLabelService.selectLabels(labelIds);
        List<String> labelNames = labels.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
        infoBO.setLabelNames(labelNames);
        return infoBO;
    }
}
